package com.xiongwei.thread;

import java.lang.invoke.VarHandle;

/**
 * 多线程同时读写共享变量,会造成逻辑错误,因此需要通过synchronized同步;
 * 同步的本质是给指定对象加锁,加锁后才能继续执行后续代码;
 * 注意加锁对象必须是同一个实例;
 * 对JVM定义的单个原子操作不需要同步.
 *
 * @author XiongWei
 * @date 2021/1/13
 */
public class ThreadSynchronize {
    public static void main(String[] args) throws InterruptedException {
        Thread[] ts = new Thread[]{new AddStudentThread(), new DecStudentThread(), new AddTeacherThread(), new DecTeacherThread()};
        for (Thread t : ts) {
            t.start();
        }
        for (Thread t : ts) {
            t.join();
        }
        System.out.println("Counter.studentCount: " + Counter.studentCount);
        System.out.println("Counter.teacherCount: " + Counter.teacherCount);
    }

}

class Counter {
    public static final Object lockTeacher = new Object();
    public static final Object lockStudent = new Object();

    public static int studentCount = 0;
    public static int teacherCount = 0;
}

class AddStudentThread extends Thread {
    @Override
    public void run() {
        for (int i=0; i<10000; i++) {
            synchronized(Counter.lockStudent) {
                Counter.studentCount += 1;
            }
        }
    }
}

class DecStudentThread extends Thread {
    @Override
    public void run() {
        for (int i=0; i<10000; i++) {
            synchronized(Counter.lockStudent) {
                Counter.studentCount -= 1;
            }
        }
    }
}

class AddTeacherThread extends Thread {
    @Override
    public void run() {
        for (int i=0; i<10000; i++) {
            synchronized(Counter.lockTeacher) {
                Counter.teacherCount += 1;
            }
        }
    }
}

class DecTeacherThread extends Thread {
    @Override
    public void run() {
        for (int i=0; i<10000; i++) {
            synchronized(Counter.lockTeacher) {
                Counter.teacherCount -= 1;
            }
        }
    }
}
